package xyz.zhno.upload.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import net.lingala.zip4j.core.ZipFile;
import net.lingala.zip4j.model.FileHeader;
import net.lingala.zip4j.model.ZipParameters;
import net.lingala.zip4j.util.Zip4jConstants;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.ResourceUtils;
import org.springframework.web.multipart.MultipartFile;
import xyz.zhno.upload.entity.File;
import xyz.zhno.upload.mapper.FileMapper;
import xyz.zhno.upload.service.FileService;

import javax.annotation.Resource;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.UUID;

/**
 * @author zh_o
 * @date 2020-12-08
 */
@Slf4j
@Service
public class FileServiceImpl extends ServiceImpl<FileMapper, File> implements FileService {

    @Resource
    private FileMapper fileMapper;

    /**
     * 文件上传
     * @param file 文件
     */
    @Override
    public void upload(MultipartFile file) throws Exception {
        log.info("传入参数: {}", file);
        // 获取原文件名称
        String oldFileName = file.getOriginalFilename();
        log.info("原文件名: {}", oldFileName);
        // 获取文件后缀
        String fileSuffix = "." + FilenameUtils.getExtension(oldFileName);
        // 生成新文件名称
        String newFileName = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()) + UUID.randomUUID().toString().replace("-", "") + fileSuffix;
        // 获取文件大小
        long size = file.getSize();
        // 获取文件类型
        String type = file.getContentType();
        // 获取文件路径
        String realPath = ResourceUtils.getURL("classpath:").getPath() + "static/files";
        // 创建日期目录
        String datePath = realPath + "/" + new SimpleDateFormat("yyyy-MM-dd").format(new Date());
        log.info("保存路径: {}", datePath);
        // 创建日期目录文件对象
        java.io.File dateDirectory = new java.io.File(datePath);
        // 判断是否存在
        if (!dateDirectory.exists()) {
            // 不存在则创建
            dateDirectory.mkdirs();
        }
        // 上传文件对象
        java.io.File uploadFile = new java.io.File(dateDirectory, newFileName);
        log.info("上传文件: {}", uploadFile.getPath());
        // 处理文件上传
        file.transferTo(uploadFile);
        log.info("压缩路径: {}", uploadFile.getPath().substring(0, uploadFile.getPath().lastIndexOf(".")) + ".zip");
        // 压缩文件
        zip(uploadFile, uploadFile.getPath().substring(0, uploadFile.getPath().lastIndexOf(".")) + ".zip");
        // 删除原文件
        uploadFile.delete();
        // 文件信息存入数据库
        log.info("新文件名: {}", newFileName);
        log.info("文件路径: {}", dateDirectory.getPath() + "/" + newFileName);
        fileMapper.insert(File.builder().fileName(newFileName).filePath(dateDirectory.getPath() + "/" + newFileName).build());
    }

    /**
     * 压缩文件
     * @param sourceFile 原文件
     * @param zipFilePath 压缩文件路径
     */
    private void zip(java.io.File sourceFile, String zipFilePath) throws Exception {
        // 创建压缩文件对象
        ZipFile zipFile = new ZipFile(zipFilePath);
        ZipParameters parameters = new ZipParameters();
        // 压缩方式
        parameters.setCompressionMethod(Zip4jConstants.COMP_DEFLATE);
        // 压缩级别
        parameters.setCompressionLevel(Zip4jConstants.DEFLATE_LEVEL_NORMAL);
        // 是否加密
        parameters.setEncryptFiles(true);
        // 加密方式
        parameters.setEncryptionMethod(Zip4jConstants.ENC_METHOD_AES);
        // 密钥算法
        parameters.setAesKeyStrength(Zip4jConstants.AES_STRENGTH_256);
        parameters.setPassword("3320");
        zipFile.addFile(sourceFile, parameters);
    }

}
